home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1985-1992 New York University
- *
- * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
- * warranty (none) and distribution info and also the GNU General Public
- * License for more details.
-
- */
-
- #include "hdr.h"
- #include "libhdr.h"
- #include "vars.h"
- #include "ifile.h"
- #include "chapprots.h"
- #include "setprots.h"
- #include "smiscprots.h"
- #include "miscprots.h"
- #include "libprots.h"
- #include "libwprots.h"
- #include "dclmapprots.h"
- #include "dbxprots.h"
- #include "errmsgprots.h"
-
- int save_trace_opt = 0;
- /* chapter 10 */
-
- static Tuple context;
-
- static void init_compunit();
- static void save_comp_info(Node);
- static void save_tree(Node, int);
- static void renumber_nodes(char *);
- static void collect_unit_nodes(Symbol);
- static void generic_declarations(Symbol, Unitdecl);
- static void save_proper_body_info(Node);
- static void save_package_instance_unit(Node);
- static void save_subprogram_instance_unit(Node);
- static void establish_context(Node);
- static void with_clause(Tuple, Node);
- static void elaborate_pragma(Node);
- static Tuple check_separate(Node);
- static Stubenv retrieve_env(Node, Node);
- static void remove_obsolete_stubs(char *);
- static char *get_unit(char *);
- static void new_unit_numbers(Node, unsigned);
-
- /*TBSL: need to review calls to sasve_subprog_info now that
- * it has an argument ds 31 oct
- */
-
- extern IFILE *TREFILE, *AISFILE, *LIBFILE;
- static Tuple elab_pragmas;
-
- /* all_vis is tuple of unit-names */
-
- static void init_compunit() /*;init_compunit*/
- {
- int i;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : init_compunit;");
-
- /* Initialize tree nodes to unit number of the new compilation unit.*/
- unit_number_now = unit_number(unit_name);
- for (i = 1; i <= seq_node_n; i++)
- N_UNIT((Node)seq_node[i]) = unit_number_now;
- }
-
- void new_compunit(char *typ, Node name_node) /*;new_compunit*/
- {
- char *name;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : new_compunit");
-
- name = N_VAL(name_node);
-
- /* Establish global name and library name for new compilation unit. */
- if (IS_COMP_UNIT){
- remove_obsolete_stubs(name);
- seq_symbol_n = 0; /* reset symbol count */
- unit_name = strjoin(typ, name);
- init_compunit();
- }
- }
-
- /* chapter 10, part b*/
- void compunit(Node node) /*;compunit*/
- {
- Node unit_body;
- Tuple added_names;
- char *id;
- Fortup ft1;
- Symbol sym;
- Fordeclared fd;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : compunit;");
-
- elab_pragmas = tup_new(0);
- stubs_to_write = set_new(0);
- all_vis = tup_new(0);
- /*context_node = N_AST1(node);*/
- unit_body = N_AST2(node);
- establish_context(node);
- /* process unit only if there were no problems in processing context */
- if (context != (Tuple)0)
- adasem(unit_body);
- if (errors == 0) {
- /* If there are no errors in any comp unit in the file, collect global
- * maps and library information after completion of this a compilation
- * unit.
- */
- if (N_KIND(unit_body) == as_separate)
- /* collect symbol table information for body (it is not a unit,
- * and must be saved explicitly here).
- */
- save_proper_body_info(unit_body);
-
- tup_frome(newtypes);
-
- if (N_KIND(unit_body) == as_insert) {
- if (N_KIND(N_AST1(unit_body)) == as_subprogram_tr)
- /* for a subprogram instance, we place renaming code in the body
- * of the subprogram. If there is some additional instantiation
- * code (bounds checks, etc.) it must be placed in a separate
- * unit on which the instantiation depends.
- */
- save_subprogram_instance_unit(node);
- else
- /* Produce two units, one for spec instance and one for body. */
- save_package_instance_unit(node);
- }
- else { /* any other kind of compilation unit.*/
- save_comp_info(node);
- }
- }
- /* Reinitialize compilation environment. */
-
- unit_name = strjoin("","");
- newtypes = tup_with(newtypes, (char *) tup_new(0));
- /* DECLARED := BASE_DECLARED;
- * Delete symbols placed in standard0 by previous compilation,
- * restoring standard0 to its initial state. added_names is a tuple
- * of identifiers added in prior compilation.
- */
- added_names = tup_new(0); /* build tuple of added identifiers */
- FORDECLARED(id, sym, DECLARED(symbol_standard0), fd);
- if (sym != (Symbol)0 && S_UNIT(sym))
- added_names = tup_with(added_names, id);
- ENDFORDECLARED(fd);
- FORTUP(id=(char *), added_names, ft1);
- dcl_undef(DECLARED(symbol_standard0), id);
- ENDFORTUP(ft1);
- tup_free(added_names);
-
- DECLARED(symbol_unmentionable) = base_declared[1];
- DECLARED(symbol_standard) = base_declared[2];
- DECLARED(symbol_ascii) = base_declared[3];
- FORDECLARED(id, sym, DECLARED(symbol_ascii), fd);
- IS_VISIBLE(fd) = TRUE;
- ENDFORDECLARED(fd);
- scope_name = symbol_standard0;
- open_scopes = tup_new(2);
- open_scopes[1] = (char *)symbol_standard0;
- open_scopes[2] = (char *)symbol_unmentionable;
- used_mods = tup_new(0);
- vis_mods = tup_new1((char *) symbol_ascii);
- scope_st = tup_new(0);
- return;
- }
-
- static void save_comp_info(Node node) /*;save_comp_info*/
- {
- /* Subsidiary to the previous procedure. In the case of a unit which is
- * a package instantiation, the current procedure is called twice, to
- * produce separate units for the instance spec and the instance body.
- */
-
- Unitdecl ud;
- char *v;
- Tuple tup;
- Set vis_units;
- int uindex, i, si;
- struct unit *pUnit;
- Fortup ft1;
- Forset fs1;
- Stubenv ev;
- char *stub_name;
-
- vis_units = set_new(tup_size(all_vis));
-
- uindex = unit_number(unit_name);
- pUnit = pUnits[uindex];
- /*PRE_COMP(unit_name) := vis_units;*/
- FORTUP(v=(char *), all_vis, ft1);
- vis_units = set_with(vis_units, (char *) unit_numbered(v));
- ENDFORTUP(ft1);
- pUnit->aisInfo.preComp = (char *)vis_units;
- pUnit->aisInfo.pragmaElab = (char *) tup_copy(elab_pragmas);
-
- /* Before writing out any info, set unit of all symbols allocated
- * while compiling this unit to current unit number
- */
- for (i = 1; i <= seq_symbol_n; i++)
- S_UNIT((Symbol)seq_symbol[i]) = uindex;
-
- save_tree(node, uindex);
- update_lib_maps(unit_name, 'u');
- pUnit->aisInfo.compDate = (char *) tup_new(0);
-
- /*UNIT_DECL(unit_name) +:= [CONTEXT, UNIT_NODES]; */
- ud = unit_decl_get(unit_name);
- if (ud == (Unitdecl)0)
- chaos("save_comp_info: unit decl missing");
- ud->ud_context = tup_copy(context);
- ud->ud_nodes = tup_copy(unit_nodes);
- unit_decl_put(unit_name, ud);
- if (!errors) {
- /* Stub environment info is now written after the tree nodes
- * are renumbered in save_tree. Also in case of erros Stub info
- * is not written to st1 file.
- */
- FORSET(si=(int), stubs_to_write, fs1)
- stub_name = lib_stub[si];
- tup = (Tuple) stub_info[si];
- ev = (Stubenv) tup[2];
- write_stub(ev, stub_name, "st1");
- ENDFORSET(fs1);
- }
- if (!errors) write_ais(uindex);
- }
-
- static void new_unit_numbers(Node root, unsigned newUnitNumber)
- /*;new_unit_number*/
- {
- unsigned nodeKind;
- Node listNode;
- Fortup ft1;
- Tuple listTuple;
-
- if (root == (Node)0 || root == OPT_NODE) return;
- N_UNIT(root) = newUnitNumber;
-
- nodeKind = N_KIND(root);
- if (N_AST1_DEFINED(nodeKind)) new_unit_numbers(N_AST1(root), newUnitNumber);
- if (N_AST2_DEFINED(nodeKind)) new_unit_numbers(N_AST2(root), newUnitNumber);
- if (N_AST3_DEFINED(nodeKind)) new_unit_numbers(N_AST3(root), newUnitNumber);
- if (N_AST4_DEFINED(nodeKind)) new_unit_numbers(N_AST4(root), newUnitNumber);
-
- if (! N_LIST_DEFINED(nodeKind)) return;
-
- listTuple = N_LIST(root);
- FORTUP(listNode=(Node), listTuple, ft1);
- new_unit_numbers(listNode, newUnitNumber);
- ENDFORTUP(ft1);
- }
-
- static void save_tree(Node root, int uindex) /*;save_tree*/
- {
- /* This procedure builds a sequential list of all the nodes in the
- * abstract syntax tree while performing a preorder scan of the tree.
- * For a given node, all its components are placed in a flat tuple
- * "tree_node". This tuple is then added to the list.
- *
- * For the C version, we need to traverse the tree to find the reachable
- * nodes, which are built up in a string reach such that reach[i] is
- * 1 if node with sequence number i is reachable, 0 otherwise.
- * We then call write_tree (lib.c) to actually write the tree.
- */
-
- int stack_max, stack_now, na, i, unit_now, nk;
- Tuple stack, a;
- Node nodes[5], n, nod;
- char *reach;
- #define STACK_INC 50
-
- if (TREFILE == (IFILE *)0) return;
- reach = emalloct((unsigned) ( seq_node_n+2) , "reach");
- reach[seq_node_n+1] = '\0'; /* mark end of string */
- for (i=0; i <= seq_node_n; i++) reach[i] = '0';
- stack_max = tup_size(unit_nodes) + STACK_INC;
- stack = tup_new(stack_max);
- for (i = 1; i <= tup_size(unit_nodes); i++){
- stack[i] = unit_nodes[i];
- #ifdef SAVE_TRACE
- save_trace("init_stack", i, (Node) stack[i]);
- #endif
- }
- stack_now = tup_size(unit_nodes);
- /* NOTE: must have STACK_INC > size of init_nodes.
- * We do not write nodes for predefined entities in C version.
- */
- unit_now = N_UNIT(root);
- stack_now++;
- stack[stack_now] = (char *) root;
- #ifdef SAVE_TRACE
- save_trace("init_root", stack_now, (Node) stack[stack_now]);
- #endif
-
- while (stack_now) {
- /*n frome stack;*/
- n = (Node) stack[stack_now];
- #ifdef DEBUG
- if (trapns>0 && N_SEQ(n) == trapns && N_UNIT(n) == trapnu) trapn(n);
- #endif
- /* define SAVE_TRACE for exhaustive trace as write tree */
- #ifdef SAVE_TRACE
- save_trace("process", stack_now, (Node) n);
- #endif
- if (N_UNIT(n) == unit_now) reach[(int)N_SEQ(n)] = '1';
- stack_now--;
- if (n == OPT_NODE) continue;
- /*tree_node := [n, N_KIND(n)];*/
- nk = N_KIND(n);
- nodes[1] = nodes[2] = nodes[3] = nodes[4] = (Node)0;
- if (N_AST1_DEFINED(nk)) nodes[1] = N_AST1(n);
- if (N_AST2_DEFINED(nk)) nodes[2] = N_AST2(n);
- if (N_AST3_DEFINED(nk)) nodes[3] = N_AST3(n);
- if (N_AST4_DEFINED(nk)) nodes[4] = N_AST4(n);
- for (i = 1; i <= 4; i++) {
- nod = nodes[i];
- /*tree_node with:= #a;*/
- if (nod == (Node)0) continue;
- /*if (tree_node /=OPT_NODE) stack with:= a(#a-i+1);*/
- if (nod == OPT_NODE) continue;
- if (stack_now == stack_max) { /* expand stack */
- stack[0] = (char *) stack_now;
- stack = tup_exp(stack, (unsigned) (stack_now+STACK_INC));
- stack[0] = (char *) stack_now;
- stack_max += STACK_INC;
- }
- /* add node to stack */
- /*tree_node with:= a(i);*/
- stack[++stack_now] = (char *) nod;
- #ifdef SAVE_TRACE
- save_trace("stack_ast", stack_now, nod);
- #endif
- }
- if (N_LIST_DEFINED(nk))
- a = N_LIST(n);
- else
- a = (Tuple)0;
- if (a != (Tuple)0 ) {
- /*tree_node with:= #a;*/
- na = tup_size(a);
- /*(for i in [1..#a])*/
- for (i = 1; i <= na; i++) {
- /*tree_node with:= a(i);*/
- nod = (Node) a[i];
- if (N_UNIT(nod) == unit_now) reach[(int)N_SEQ(nod)] = '1';
- /*stack with:= a(#a-i+1);*/
- if (stack_now == stack_max) {
- stack[0] = (char *) stack_now;
- stack = tup_exp(stack, (unsigned) stack_now+STACK_INC);
- stack[0] = (char *) stack_now;
- stack_max += STACK_INC;
- }
- stack[++stack_now] = (char *) nod;
- #ifdef SAVE_TRACE
- save_trace("stack_list", stack_now, nod);
- #endif
- }
- }
- }
- renumber_nodes(reach);
- write_tre(uindex, N_SEQ(root), reach);
- efreet(reach, "reach");
- tup_free(stack);
- }
-
- static void renumber_nodes(char *reach) /*;renumber_nodes*/
- {
- /* This procedure renumbers the nodes so that the nodes which are live
- * (not dead) and need to be written out in the tree (trc) file are
- * contigous and the seq_node array is therefore dense. This reduces
- * the size of seq_node necessary for separate compilation and in the
- * code generator phase. In addition the offset table written in the trc
- * file will also be reduced with this compressed version. The scheme
- * is relatively simple in that all nodes that are unreachable are
- * exchanged with positions that are reachable which appear later in
- * the list (tuple). Only one pass over the nodes is necessary using this
- * method, so it is quite efficient.
- * Note that seq_node_n is changed in this procedure.
- */
-
- int i, j;
- int reachable_node_found;
- Node nod, unreachable_node;
-
- j = seq_node_n;
- for (i = 1; i <= j; i++) {
- /* First search rightward for a node which is unreachable (where reach
- * is 0 for that element). This will then be exchanged with a node
- * which is reachable which is found by searching the list leftward.
- * Ultimately the left and right pointers (i & j) will converge.
- */
- if (reach[i] == '1') continue;
- reachable_node_found = 0;
-
- /* Search for reachable node from the right */
- for (; j > i; j--) {
- if (reach[j] == '1') {
- reachable_node_found = 1;
- break;
- }
- }
- /* If there is no reachable node found any more we are done with the
- * compression.
- */
- if (!reachable_node_found) break;
- nod = (Node) seq_node[j];
- unreachable_node = (Node) seq_node[i];
- /* Exchange positions of the two nodes and set their seqeunce number
- * to the respective new position numbers.
- * Currently the node in seq_node[i] cannot be wiped out since it is
- * still needed because of save_package_instance.
- */
- seq_node[i] = (char *) nod;
- seq_node[j] = (char *) unreachable_node;
- N_SEQ(nod) = i;
- N_SEQ(unreachable_node) = j;
- reach[i] = '1';
- reach[j] = '0';
- }
- seq_node_n = i - 1;
- }
-
- #ifdef SAVE_TRACE
- void save_trace(char *s, int n, Node nod)
- {
- if (save_trace_opt == 0) return;
- printf("%11s %d\n", s, n);
- zpnod(nod);
- }
- #endif
- void save_trace_init()
- {
- save_trace_opt++;
- }
-
- Tuple unit_symbtab(Symbol unit_unam, char unit_typ) /*;unit_symbtab*/
- {
- /* Collect symbol table entries for all entities declared in a compila-
- * tion unit, including inner units and blocks. We iterate over the
- * symbol table, and save all objects that are declared in the unit and
- * in inner scopes. For non-generic package bodies, we omit the decla-
- * rations that appear in the visible part, and are already saved with
- * the package spec.
- */
-
- Tuple symb_map;
- Tuple ignore;
- Set scopes, seen;
- Symbol u_name, sc, sym;
- char *id;
- Fordeclared fd1;
- Forprivate_decls fp1;
- Private_declarations pd;
- int ignore_n;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : unit_symbtab:");
-
- unit_nodes = tup_new(0);
- if (errors) return unit_nodes;
-
- symb_map = tup_new(0);
- ignore = tup_new(0);
- ignore_n = 0;
- if (NATURE(unit_unam) == na_package && unit_typ == 'u') {
- ignore = tup_exp(ignore, 10);
- ignore_n = 0;
- FORDECLARED(id, u_name, DECLARED(unit_unam), fd1);
- if (IS_VISIBLE(fd1)) {
- if (tup_mem((char *) u_name, ignore)) continue;
- if (ignore_n>=tup_size(ignore)) {
- ignore = tup_exp(ignore, (unsigned) (ignore_n+10));
- }
- ignore_n += 1;
- ignore[ignore_n] = (char *) u_name;
- }
- ENDFORDECLARED(fd1);
- }
-
- /* first, collect the nodes referenced in the current unit Symbtab record.
- * then, iterate through it's declared map to get declarations in inner
- * scopes.
- */
- collect_unit_nodes(unit_unam);
-
- ignore[0] = (char *) ignore_n;
- seen = set_new1((char *) unit_unam);
- scopes = set_copy(seen);
-
- while (set_size(scopes) != 0) {
- sc = (Symbol) set_from(scopes);
- FORDECLARED(id, u_name, DECLARED(sc), fd1);
- if (! tup_mem((char *)u_name, ignore) ) { /* save its info. */
- /* Collect the AST nodes that appear in SYMBTAB, and may thus*/
- /* be needed for separate compilation and code generation.*/
- collect_unit_nodes(u_name);
- /*symb_map(u_name) := SYMBTABF(u_name);*/
- symb_map = sym_save(symb_map, u_name, unit_typ);
- }
- /* note that na_enum symbols have their literal map stored in the
- * DECLARED field and so should be skipped in next test
- * IS THIS STILL TRUE????
- */
- if (NATURE(u_name) == na_enum) continue;
-
- if (DECLARED(u_name) != (Declaredmap)0
- && (!set_mem((char *)u_name, seen ) )){
- /* collect local declarations of inner scope.*/
- scopes = set_with(scopes, (char *) u_name);
- seen = set_with(seen, (char *) u_name);
- }
- ENDFORDECLARED(fd1);
-
- if (NATURE(sc) == na_package || NATURE(sc) == na_package_spec
- || NATURE(sc) == na_generic_package
- || NATURE(sc) == na_generic_package_spec) {
- /* Collect and save nodes attatched to private_decls field */
- pd = (Private_declarations) private_decls(sc);
- FORPRIVATE_DECLS(sym, u_name, pd, fp1);
- collect_unit_nodes(u_name);
- ENDFORPRIVATE_DECLS(fp1);
- }
- }
- /* We include in symb_map the information for the unit itself, which is
- * declared in STANDARD.
- */
- /* TBSL: get rid of this KLUDGE
- * for generic subprograms, save symbol regardless of unit, so that the
- * unit name of body is retrievable after being overwritten by spec
- */
- if (NATURE(unit_unam) == na_generic_procedure
- || NATURE(unit_unam) == na_generic_function
- || NATURE(unit_unam) == na_generic_package)
- symb_map = sym_save(symb_map, unit_unam, 's');
- else
- symb_map = sym_save(symb_map, unit_unam, unit_typ);
- set_free(seen);
- set_free(scopes);
- /* replace symbol pointers to copy of symbol table entries */
- tup_free(ignore);
- return symb_map;
- }
-
- static void collect_unit_nodes(Symbol u_name) /*;collect_unit_nodes*/
- {
- /* Collect the AST nodes that appear in SYMBTAB, and may thus*/
- /* be needed for separate compilation and code generation.*/
-
- int nat, i, size;
- Symbol typ;
- Tuple sig, discr_map, gen_list, tup;
- Fortup ft1;
-
- typ = TYPE_OF(u_name);
- nat = NATURE(u_name);
- if (typ == symbol_incomplete || typ == symbol_private
- || typ == symbol_limited_private)
- nat = na_record; /* signature has form of record signature */
-
- switch (nat) {
- case na_constant:
- case na_discriminant:
- case na_in:
- unit_nodes_add((Node) default_expr(u_name));
- break;
- case na_type:
- sig = SIGNATURE(u_name);
- if (sig == (Tuple)0)
- chaos("unit_symbtab subtype - no signature");
- if ((int) sig[1] == CONSTRAINT_DELTA) {
- unit_nodes_add((Node) numeric_constraint_low(sig));
- unit_nodes_add((Node) numeric_constraint_high(sig));
- unit_nodes_add((Node) numeric_constraint_delta(sig));
- unit_nodes_add((Node) numeric_constraint_small(sig));
- }
- break;
- case na_subtype:
- sig = SIGNATURE(u_name);
- if (sig == (Tuple)0)
- chaos("unit_symbtab subtype - no signature");
- if (is_scalar_type(u_name)) {
- unit_nodes_add((Node) numeric_constraint_low(sig));
- unit_nodes_add((Node) numeric_constraint_high(sig));
- if ((int) sig[1] == CONSTRAINT_DELTA) {
- unit_nodes_add( (Node) numeric_constraint_delta(sig));
- unit_nodes_add( (Node) numeric_constraint_small(sig));
- }
- else if ((int) sig[1] == CONSTRAINT_DIGITS) {
- unit_nodes_add( (Node) numeric_constraint_digits(sig));
- }
- }
- else if (is_record(u_name)) {
- discr_map = (Tuple) sig[2];
- size = tup_size(discr_map);
- for (i = 1; i <= size; i+=2)
- unit_nodes_add((Node) discr_map[i+1]);
- }
- break;
- case na_enum:
- sig = SIGNATURE(u_name);
- if (sig == (Tuple)0) chaos("unit_symbtab enum - no signature");
- unit_nodes_add((Node) numeric_constraint_low(sig));
- unit_nodes_add((Node) numeric_constraint_high(sig));
- break;
- case na_record:
- unit_nodes_add((Node) invariant_part(u_name));
- unit_nodes_add((Node) variant_part(u_name));
- unit_nodes_add((Node) discr_decl_tree(u_name));
- break;
- case na_procedure_spec:
- case na_function_spec:
- case na_entry:
- case na_entry_family:
- case na_generic_procedure_spec:
- case na_generic_function_spec:
- unit_nodes_add((Node) formal_decl_tree(u_name));
- break;
- /*
- * Clear out the formal_decl_tree fields of procedure or
- * function symbols since these are not needed for
- * conformance checks (only na_procedure_spec or
- * na_function_spec symbols need this entry).
- */
- case na_procedure:
- case na_function:
- formal_decl_tree(u_name) = (Symbol)0;
- break;
- /*
- * the nodes of generic packages(specs and bodies) or nodes of generic
- * subprograms bodies are not automatically read in. They are brought
- * in explicitly upon instantiation. Default values for generic para-
- * meters however must be read in for instantiation. The generic_list
- * is a tuple of pairs [name, initial value] which we unpack here.
- */
- case na_generic_package_spec:
- case na_generic_package:
- case na_generic_function:
- case na_generic_procedure:
- sig = SIGNATURE(u_name);
- gen_list = (Tuple)sig[1];
- FORTUP(tup=(Tuple), gen_list, ft1)
- unit_nodes_add((Node)tup[2]);
- ENDFORTUP(ft1);
- break;
- }
- }
-
- void save_subprog_info(Symbol unit_unam) /*;save_subprog_info*/
- {
- /* Save declarations for a subprogram specification or body which is a
- * compilation unit.
- */
-
- int uindex;
- Unitdecl ud;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : save_subprog_info");
-
- if (IS_COMP_UNIT){
- if (unit_unam == (Symbol)0) {
- #ifdef ERRNUM
- errmsgn(11, 10, (Node)0);
- #else
- errmsg("Invalid compilation unit", "none", (Node)0);
- #endif
- return;
- }
- /* get unit number (assign new one if needed) */
- uindex = unit_number(unit_name);
-
- /* For subprograms, UNIT_DECL has 4 fields:
- * 1. unique name of subprogram
- * 2. symbol table entries
- * 3. declared maps for subprogram's scope
- * ( for possible late instantiations)
- * 4. context (supplied in compunit)
- *
- * case nature(unit_unam) of
- * (na_procedure_spec, na_function_spec,
- * na_generic_procedure_spec, na_generic_function_spec):
- * decmap := {[unit_unam, declared(unit_unam)]};
- *
- * TBSL for generics
- * (na_generic_procedure, na_generic_function):
- * decmap := generic_declarations();
- * decmap(unit_unam) := declared(unit_unam);
- *
- * else
- * TBSL for generics
- * decmap := generic_declarations();
- * end case;
- *
- * UNIT_DECL(unit_name) :=
- * [unit_unam, unit_symbtab(unit_unam), decmap, [], {}];
- */
- ud = unit_decl_get(unit_name);
- if (ud == (Unitdecl)0) ud = unit_decl_new();
- ud->ud_unam = unit_unam;
- NEEDNAME(unit_unam) = TRUE;
- ud->ud_useq = S_SEQ(unit_unam);
- ud->ud_unit = S_UNIT(unit_unam);
- ud->ud_symbols = unit_symbtab(unit_unam, 'u');
- if (DECLARED(unit_unam) == (Declaredmap)0) {
- ud->ud_decscopes = (Tuple) 0;
- ud->ud_decmaps = (Tuple) 0;
- }
- else {
- ud->ud_decscopes = tup_new1((char *) unit_unam);
- ud->ud_decmaps = tup_new1(
- (char *) dcl_copy(DECLARED(unit_unam)));
- }
- unit_decl_put(unit_name, ud);
- }
- }
-
- static void generic_declarations(Symbol unit_unam, Unitdecl ud)
- /*;generic_declarations*/
- {
- /* This procedure collects the contents of declared maps within generic
- * subunits, for possible subsequent late instantiations.
- */
-
- Tuple decscopes, decmaps;
- Set decl_scopes, scopes, seen;
- Symbol u_name, sc;
- char *id;
- Fordeclared fd1;
- decscopes = tup_new(0);
- decmaps = tup_new(0);
-
- if (NATURE(unit_unam) == na_generic_package)
- decl_scopes = tup_new1((char *) unit_unam);
- else
- decl_scopes = tup_new(0);
-
- /* In SETL want to iterate over declared - i.e., we need to know domain
- * of declared. We take this by looking at all symbols defined in current
- * unit for which declared field defined. This includes some extra symbols,
- * I think due to private decls, but these extra maps seem harmless.
- */
- scopes = set_new1((char *)unit_unam);
- seen = set_new(0);
- while (set_size(scopes) != 0) {
- sc = (Symbol) set_from(scopes);
- seen = set_with(seen, (char *)sc);
- if (DECLARED(sc) != (Declaredmap)0) {
- FORDECLARED(id, u_name, DECLARED(sc), fd1);
- if (DECLARED(u_name) != (Declaredmap)0
- &&(!set_mem((char *)u_name, seen))) {
- /* collect local declarations of inner scope.*/
- if (NATURE(u_name) == na_generic_procedure
- || NATURE(u_name) == na_generic_function
- || NATURE(u_name) == na_generic_package)
- decl_scopes = set_with(decl_scopes, (char *)u_name);
- else if (NATURE(u_name) == na_package)
- scopes = set_with(scopes, (char *) u_name);
- }
- ENDFORDECLARED(fd1);
- }
- }
-
- seen = set_new(0);
-
- while (set_size(decl_scopes) != 0) {
- sc = (Symbol) set_from(decl_scopes);
- seen = set_with(seen, (char *)sc);
- decscopes = tup_with(decscopes, (char *) sc);
- decmaps = tup_with(decmaps, (char *) dcl_copy(DECLARED(sc)));
- FORDECLARED(id, u_name, DECLARED(sc), fd1);
- if (DECLARED(u_name) != (Declaredmap)0
- &&(!set_mem((char *)u_name, seen)))
- /* collect local declarations of inner scope.*/
- decl_scopes = set_with(decl_scopes, (char *) u_name);
- ENDFORDECLARED(fd1);
- }
-
- ud->ud_decscopes = decscopes;
- ud->ud_decmaps = decmaps;
- set_free(seen);
- set_free(scopes);
- }
-
- void save_spec_info(Symbol unit_unam, Tuple old_vis) /*;save_spec_info*/
- {
- /* Build UNIT_DECL for a package spec. that is a compilation unit.*/
-
- Symbol sn;
- int i, uindex;
- Tuple decscopes, decmaps, decl_scopes;
- Unitdecl ud;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : save_spec_info");
-
- /* This was here as early as 1983, and now not only seems useless, but
- * is WRONG !!!
- * At end of module_body, we iterate over all inner scopes, and the presence
- * of generic inside scope of instance results in looping.
- if (NATURE(unit_unam) == na_generic_package_spec) {
- * save name within its own declarations, to simplify retrieval at
- * instantiation time.
- dcl_put(DECLARED(unit_unam), original_name(unit_unam), unit_unam);
- }
- */
- /*
- * For package specifications, UNIT_DECL has 6 fields.
- * 1. unique name of compilation unit
- * 2. symbol table entries
- * 3. declared maps for program defined scopes
- * 4. vis_mods
- * 5. difference between declared and visible
- * 6. context (supplied in comp_unit)
- */
- decscopes = tup_new(0);
- decmaps = tup_new(0);
- /* In SETL want to iterate over declared - i.e., we need to know domain
- * of declared. We take this by looking at all symbols defined in current
- * unit for which declared field defined. This includes some extra symbols,
- * I think due to private decls, but these extra maps seem harmless.
- */
- decl_scopes = tup_new(0);
- for (i = 1; i <= seq_symbol_n; i++)
- if (DECLARED((Symbol)seq_symbol[i]) != (Declaredmap)0)
- decl_scopes = tup_with(decl_scopes, seq_symbol[i]);
- for (i = 1; i <= tup_size(decl_scopes); i++){
- sn = (Symbol) decl_scopes[i];
- decscopes = tup_with(decscopes, (char *) sn);
- decmaps = tup_with(decmaps, (char *) dcl_copy(DECLARED(sn)));
- }
- /*decmap := {[sn, dsn] : dsn = declared(sn) | sn notin p_s};
- *
- * Notvis keeps track of things declared but not visible
- */
- #ifdef TBSL
- -- note change in def of notvis 5-jan-85:
- only define notvis
- -- is vis is not om.
- notvis :
- = {
- };
- (for [sn, dsn] in decmap | visible(sn) /= om)
- notvis(sn) :
- = {
- dec:
- dec in dsn | dec notin visible(sn) };
- end for;
- notvis = tup_new(0);
- #endif
- /* UNIT_DECL(unit_name) :=
- * [unit_unam, unit_symbtab(unit_unam), decmap, old_vis, notvis];
- * In C version have different format .
- */
-
- if (!unit_numbered(unit_name)) uindex = unit_number(unit_name);
- ud = unit_decl_get(unit_name);
- if (ud == (Unitdecl)0) ud = unit_decl_new();
- ud->ud_unam = unit_unam;
- NEEDNAME(unit_unam) = TRUE;
- ud->ud_useq = S_SEQ(unit_unam);
- ud->ud_unit = S_UNIT(unit_unam);
- ud->ud_symbols = unit_symbtab(unit_unam, 'u');
- ud->ud_decscopes = decscopes;
- ud->ud_oldvis = tup_copy(old_vis);
- ud->ud_decmaps = decmaps;
- unit_decl_put(unit_name, ud);
- }
-
- void save_body_info(Symbol nam) /*;save_body_info*/
- {
- /* For a package body, only the symbol table information needs to be
- * saved, for purposes of generic instantiation. Visibility information
- * is not kept.
- */
-
- int uindex;
- Unitdecl ud;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC: save_body_info");
-
- if (IS_COMP_UNIT) {
- /*
- * UNIT_DECL(unit_name) := [nam, unit_symbtab(nam),
- * generic_declarations(), [], {}];
- */
- uindex = unit_number(unit_name);
- ud = unit_decl_get(unit_name);
- if (ud == (Unitdecl)0) ud = unit_decl_new();
- ud->ud_unam = nam;
- NEEDNAME(nam) = TRUE;
- ud->ud_useq = S_SEQ(nam);
- ud->ud_unit = S_UNIT(nam);
- ud->ud_symbols = unit_symbtab(nam, 'u');
- generic_declarations(nam, ud);
- unit_decl_put(unit_name, ud);
- }
- }
-
- static void save_proper_body_info(Node node) /*;save_proper_body_info*/
- {
- Node proper_node, spec, name_node;
- Symbol unit_unam;
- Unitdecl ud;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : save_proper_body_info");
-
- proper_node = N_AST2(node);
- if (N_KIND(proper_node) == as_generic_procedure
- || N_KIND(proper_node) == as_generic_function) {
- spec = N_AST1(proper_node);
- name_node = N_AST1(spec);
- }
- /* For subprogram proper bodies the unique name is stored in the
- * proper_node itself.
- */
- else if (N_KIND(proper_node) == as_subprogram_tr) {
- name_node = proper_node;
- }
- else
- name_node = N_AST1(proper_node);
-
- unit_unam = N_UNQ(name_node);
-
- /* UNIT_DECL(unit_name) :=
- * [unit_unam, unit_symbtab(unit_unam), generic_declarations(), [], {}];
- */
-
- ud = unit_decl_get(unit_name);
- if (ud == (Unitdecl)0) ud = unit_decl_new();
- ud->ud_unam = unit_unam;
- NEEDNAME(unit_unam) = TRUE;
- ud->ud_useq = S_SEQ(unit_unam);
- ud->ud_unit = S_UNIT(unit_unam);
- ud->ud_symbols = unit_symbtab(unit_unam, 'u');
-
- #ifdef TBSL
- handle generic_declarations
- #endif
-
- unit_decl_put(unit_name, ud);
- }
-
- static void save_package_instance_unit(Node node)/*;save_package_instance_unit*/
- {
- /* If a unit is a package instance, it is necessary to construct two
- * units, one for the spec and one for the body of the instance.
- */
-
- Node context_node, unit_body, spec_node, body_node, id_node, b_node;
- char *nam;
- Symbol unam;
- Tuple tup;
- Unitdecl ud;
- int saved_seq_node_n, i;
-
- context_node = N_AST1(node);
- unit_body = N_AST2(node);
-
- /* The unit body is an insert node; unpack spec and body of instance.*/
- tup = N_LIST(unit_body);
- spec_node = (Node) tup[1];
- id_node = N_AST1(spec_node);
- body_node = N_AST1( unit_body);
-
- N_AST1(node) = context_node;
- N_AST2(node) = spec_node;
- unit_name[0] = 's'; /* set to spec */
- unit_name[1] = 'p';
-
- /* Build a node for the package instance, and rebuild compilation info.
- * for it. Its UNIT_DECL need not contain symbol table info, which is
- * emitted with the spec, and always retrieved at the same time.
- * TBSL: what if this is a delayed instance?
- */
- nam = unit_name_name(unit_name);
- b_node = node_new(as_unit);
- N_AST1(b_node) = context_node;
- N_AST2(b_node) = body_node;
-
- /* Since nodes for the spec and body were created at the same time they
- * both have the same unit number.
- * After the spec is written change the unit field of all the body nodes
- * to reflect its unit.
- */
- unam = N_UNQ(id_node);
- /* Set the nature of the symbol to be as a package spec so that the private
- * declarations (OVERLOADS field) is set upon reading the spec of the
- * instantiated package. Reset to package after the unit is written.
- */
- NATURE(unam) = na_package_spec;
- /* Save the old value of seq_node_n since this will be changed when
- * renumber_nodes is called by save_tree and sets seq_node_n to the
- * number of live and useful nodes. However all the nodes in seq_node need
- * to be accessable for working with the package body nodes, so we will
- * have to reset seq_node_n to the saved value. This is basically due to
- * the artifact of how instantiated package body are handled.
- */
- saved_seq_node_n = seq_node_n;
- save_comp_info(node);
- seq_node_n = saved_seq_node_n;
- OVERLOADS(unam) = 0;
- NATURE(unam) = na_package;
-
- all_vis = tup_with(all_vis, unit_name); /* body depends on spec.*/
- unit_name = strjoin("bo", nam);
- unit_number_now = unit_number(unit_name);
- new_unit_numbers(b_node, unit_number_now);
- /* Set the number of symbols to be 0 so that the unit number of the symbol
- * for the package is not reset to be the unit number for the body.
- */
- seq_symbol_n = 0;
- unit_nodes = tup_new(0);
- unam = N_UNQ(id_node);
- ud = unit_decl_new();
- ud->ud_unam = unam;
- ud->ud_useq = S_SEQ(unam);
- ud->ud_unit = S_UNIT(unam);
- ud->ud_symbols = tup_new(0);
- unit_decl_put(unit_name, ud);
-
- /*UNIT_DECL(unit_name) := [nam, {}, {}, [], {}];*/
- /* TBSL: note that now setting five components ds 7 dec 84 */
-
- save_comp_info(b_node);
- }
-
- static void save_subprogram_instance_unit(Node node)
- /*; save_subprogram_instance_unit */
- {
- /* The instantiation code (renamings of formals by actuals, bounds checks)
- * are elaborated before the body of the instance. If the instance is a
- * unit, the instantiation code must in fact be placed in a anonymous unit
- * on which the instantiation depends.
- * For now, we place the renamings in the dclarative part of the procedure,
- * which is inefficient but harmless.
- * TBSL: construction of anonymous unit with the rest
- */
-
- Tuple i_code , i_decls, i_checks, ntup;
- Node instance, decl_node, n, ins_node, context_node, b_node;
- int i, k;
-
- context_node = N_AST1(node);
- ins_node = N_AST2(node); /* insert node */
- i_code = N_LIST(ins_node); /* instantiation code */
- instance = N_AST1(ins_node); /* subprogram instance*/
- N_AST2(node) = instance;
- decl_node = N_AST2(instance);
- i_decls = tup_new(0);
- i_checks = tup_new(0);
- for ( i = 1; i <= tup_size(i_code); i++) {
- n = (Node)tup_fromb(i_code);
- k = N_KIND(n);
- if (k == as_raise || k == as_check_bounds || k == as_check_discr)
- i_checks = tup_with(i_checks, (char *) n);
- else
- i_decls = tup_with(i_decls, (char *) n);
- }
-
- ntup = tup_add(i_decls, N_LIST(decl_node));
- tup_free(N_LIST(decl_node));
- N_LIST(decl_node) = ntup;
-
- b_node = node_new(as_unit);
- N_AST1(b_node) = context_node;
- N_AST2(b_node) = instance;
- save_comp_info(b_node);
-
- if (tup_size(i_checks) > 0)
- chaos("subprogram_instance_unit: checks left over");
- }
-
- static void establish_context(Node node) /*;establish_context*/
- {
- char *name, *nam;
- Fortup ft1, ft2, ft3;
- Node un_node, clause_node, uw_node, unit_node;
- Node context_node, spec, name_node;
- int kind, i, nk;
- Tuple tupn, tup, use_nodes, with_tup;
- char *spec_name;
- Tuple elaborate_list, with_list, nam_list, inherited_context = (Tuple)0;
- Unitdecl spec_decl;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : establish_context(name);");
-
- context_node = N_AST1(node);
- unit_node = N_AST2(node);
-
- /* Flatten with- and use-clauses from context node.*/
-
- context = tup_new(0);
- with_list = N_LIST(context_node);
- elaborate_list = tup_new(0);
- /* NOTE that ELABORATE pragmas can only appear immediately after a
- * context_clause. The necessary checks to insure that this condition
- * is met have not been made.
- */
- use_nodes = tup_new(0);
- with_tup = tup_new(0);
- FORTUP(clause_node=(Node), with_list, ft1);
- FORTUP(uw_node=(Node), N_LIST(clause_node), ft2);
- kind = N_KIND(uw_node);
- if (kind == as_with || kind == as_use) {
- tupn = tup_new(tup_size(N_LIST(uw_node)));
- FORTUPI(un_node=(Node), N_LIST(uw_node), i, ft3);
- tupn[i] = N_VAL(un_node);
- ENDFORTUP(ft3);
- tup = tup_new(2);
- tup[1] = (char *) kind;
- tup[2] = (char *) tupn;
- context = tup_with(context, (char *) tup);
- if (kind == as_use) {
- /* save nodes for subsequent call to resolve_use_clause */
- use_nodes = tup_with(use_nodes, (char *)uw_node);
- /* check that it appears in a previous with clause */
- FORTUP(name = (char *), tupn, ft3);
- if (!tup_memstr(name, with_tup))
- #ifdef ERRNUM
- str_errmsgn(12, name, 13, uw_node);
- #else
- errmsg_str("% does not appear in previous with clause",
- name, "10.1.1", uw_node);
- #endif
- ENDFORTUP(ft3);
- }
- else {
- with_tup = tup_add(with_tup, tupn);
- }
- }
- else {
- elaborate_list = tup_with(elaborate_list, (char *) uw_node);
- }
- ENDFORTUP(ft2);
- ENDFORTUP(ft1);
-
- /* For bodies and proper bodies, collect any context specification
- * inherited from parent unit or from spec.
- */
- nk = N_KIND(unit_node);
- if (nk == as_separate) {
- inherited_context = check_separate(unit_node);
- if (inherited_context == (Tuple)0) {
- context = (Tuple) 0; /* indicates error */
- return;
- }
- }
- else if (nk == as_package_body) {
- name_node = N_AST1(unit_node);
- name = N_VAL(name_node);
- current_node = name_node;
- get_specs(name);
- all_vis = tup_with(all_vis, strjoin("sp", name));
- /* all_vis with:= ['spec', name]; */
- spec_decl = unit_decl_get(strjoin("sp", name));
- if (spec_decl != (Unitdecl)0)
- inherited_context = spec_decl->ud_context;
- }
- else if (nk == as_subprogram) {
- /* may have been subprogram spec.*/
- spec = N_AST1(unit_node);
- name_node = N_AST1(spec);
- name = N_VAL(name_node);
- spec_name = strjoin("ss", name);
- if (retrieve(spec_name) )
- all_vis = tup_with(all_vis, spec_name);
-
- spec_decl = unit_decl_get(spec_name);
- if (spec_decl != (Unitdecl)0)
- inherited_context = spec_decl->ud_context;
- }
-
- if (inherited_context == (Tuple) 0)
- /* this may occur if there were errors in previous units */
- inherited_context = tup_new(0);
-
- /* process inherited context specification */
- FORTUP(tup=(Tuple), inherited_context, ft1);
- kind = (int) tup[1];
- nam_list = (Tuple) tup[2];
-
- if (kind == as_with)
- with_clause(nam_list, current_node);
- else if (kind == as_use) {
- /* rebuild list of name nodes for use_clause */
- un_node = node_new(as_use);
- N_LIST(un_node) = tup_new(tup_size(nam_list));
- FORTUPI(nam = (char *), nam_list, i, ft2);
- name_node = node_new(as_simple_name);
- N_VAL(name_node) = nam;
- N_LIST(un_node)[i] = (char *)name_node;
- ENDFORTUP(ft2);
- use_clause(un_node);
- }
- ENDFORTUP(ft1);
-
- /* Process the given context specification. */
- FORTUP(tup=(Tuple), context, ft1);
- kind = (int) tup[1];
- nam_list = (Tuple) tup[2];
-
- if (kind == as_with)
- with_clause(nam_list, context_node);
- ENDFORTUP(ft1);
-
- FORTUP(un_node=(Node), use_nodes, ft1);
- use_clause(un_node);
- ENDFORTUP(ft1);
- tup_free(use_nodes);
-
- FORTUP(name_node=(Node), elaborate_list, ft1);
- elaborate_pragma(name_node);
- ENDFORTUP(ft1);
-
- context = tup_add(inherited_context, context);
- }
-
- static void with_clause(Tuple nam_list, Node context_node) /*;with_clause */
- {
- char *nam, *unit;
- Fortup ft;
-
- FORTUP(nam=(char *), nam_list, ft);
- unit = get_unit(nam);
- if (strlen(unit) >0 )
- all_vis = tup_with(all_vis, unit);
- else {
- #ifdef ERRNUM
- str_errmsgn(14, nam, 13, context_node);
- #else
- errmsg_str("Unknown unit in with clause: %", nam, "10.1.1",
- context_node);
- #endif
- all_vis = tup_with(all_vis, strjoin("sp", nam));
- }
- ENDFORTUP(ft);
- }
-
- static char *get_unit(char *nam) /*;get_unit*/
- {
- int exists, i;
- char *unit, *unit1, *unit2, *su, *body_name;
- Fortup ft1;
- Node id_node;
- Symbol namsym, unit_unam, scope;
- Tuple s_info, decscopes, decmaps;
- Unitdecl ud;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : get_unit");
-
- exists = FALSE;
- for(i = 1; i <= unit_numbers; i++) {
- unit = pUnits[i]->libUnit;
- unit2 = unit_name_name(unit);
- unit1 = unit_name_type(unit);
- if (streq(unit2, nam)
- && (streq(unit1, "ss") || streq(unit1, "sp"))) {
- exists = TRUE;
- break;
- }
- }
- if (exists == FALSE) {
- su = strjoin("su", nam);
- for(i = 1; i <= unit_numbers; i++) {
- unit = pUnits[i]->libUnit;
- if (streq(su, unit)) {
- exists = TRUE;
- break;
- }
- }
- }
-
- if (exists) {
- if (cdebug2 > 3) TO_ERRFILE(strjoin("unit ", unit));
-
- if (streq(unit_name_type(unit), "sp")) {
- /* puts created symbol in standard0 scope*/
- unit_unam = get_specs(nam);
-
- namsym = dcl_get(DECLARED(symbol_standard0), nam);
- if (NATURE(unit_unam) != na_generic_package
- && NATURE(unit_unam) != na_generic_package_spec)
- vis_mods =tup_with(vis_mods, (char *) namsym);
- }
- else { /* unit is a subprogram */
- if (retrieve(unit) ) {
- /* [unit_unam, s_info, decmap] := UNIT_DECL(unit); */
- ud = unit_decl_get(unit);
- unit_unam = ud->ud_unam;
- s_info = ud->ud_symbols;
- decscopes = ud->ud_decscopes;
- decmaps = ud->ud_decmaps;
-
- /* Restore symbol table entries.*/
- symtab_restore(s_info);
-
- /* (for decls = decmap(scope))
- * declared(scope) := decls;
- * end;
- */
- FORTUPI(scope=(Symbol), decscopes, i, ft1);
- DECLARED(scope) = dcl_copy((Declaredmap) decmaps[i]);
- ENDFORTUP(ft1);
- }
- dcl_undef(DECLARED(symbol_standard0), nam);
- dcl_put(DECLARED(symbol_standard0), nam, unit_unam);
- }
- /* for generic specs retrieve body info */
- if (NATURE(unit_unam) == na_generic_package_spec) {
- body_name = strjoin("bo", nam);
- if (retrieve(body_name)) {
- ud = unit_decl_get(body_name);
- unit_unam = ud->ud_unam;
- s_info = ud->ud_symbols;
- decscopes = ud->ud_decscopes;
- decmaps = ud->ud_decmaps;
-
- /* SYMTAB restore */
- symtab_restore(s_info);
-
- FORTUPI(scope=(Symbol), decscopes, i, ft1);
- if (decmaps[i] != (char *)0)
- DECLARED(scope) = dcl_copy((Declaredmap) decmaps[i]);
- ENDFORTUP(ft1);
- }
- }
- else if (NATURE(unit_unam) == na_generic_procedure_spec
- || NATURE(unit_unam) == na_generic_function_spec) {
- body_name = strjoin("su", nam);
- /* CHECK HOW MUCH OF THIS IS NECESSARY !!! */
- if (retrieve(body_name)) {
- ud = unit_decl_get(body_name);
- unit_unam = ud->ud_unam;
- s_info = ud->ud_symbols;
- decscopes = ud->ud_decscopes;
- decmaps = ud->ud_decmaps;
-
- /* Restore symbol table entries.*/
- symtab_restore(s_info);
-
- /* (for decls = decmap(scope))
- * declared(scope) := decls;
- * end;
- */
- FORTUPI(scope=(Symbol), decscopes, i, ft1);
- DECLARED(scope) = dcl_copy((Declaredmap) decmaps[i]);
- ENDFORTUP(ft1);
- }
- dcl_undef(DECLARED(symbol_standard0), nam);
- dcl_put(DECLARED(symbol_standard0), nam, unit_unam);
- }
- return unit;
- }
- else { /* Unit is not in library*/
- id_node = node_new(as_simple_name);
- N_VAL(id_node) = (char *) nam;
- check_old(id_node);
- if (N_UNQ(id_node) == symbol_undef) { /* safe to add it, */
- namsym = find_new(N_VAL(id_node)); /* To avoid error */
- N_UNQ(id_node) = namsym;
- #ifdef TBSL
- visible(nam) :
- = {
- };
- $ in subsequent USE
- #endif
- }
- return strjoin("","");
- }
- }
-
- static void elaborate_pragma(Node node) /*;elaborate_pragma*/
- {
- Node arg_list_node;
- Node i_node, e_node, name_node, arg_node;
- Tuple arg_list;
- Fortup ft1;
- char *nam;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : elaborate_pragma");
-
- arg_list_node = N_AST2(node);
- arg_list = N_LIST(arg_list_node);
- FORTUP(arg_node=(Node), arg_list, ft1);
- i_node = N_AST1(arg_node);
- e_node = N_AST2(arg_node);
- /*For now, disregard named associations.*/
- if (cdebug2 > 3) TO_ERRFILE("all_vis : ");
- name_node = N_AST1(e_node); /* extract simple_name node.*/
- nam = N_VAL(name_node);
- if (tup_memstr(strjoin("sp", nam), all_vis)) {
- /*if ['spec', nam] in all_vis then*/
- elab_pragmas =tup_with(elab_pragmas, strjoin("bo", nam));
- /* package body needed.*/
- }
- else if (tup_memstr(strjoin("ss", nam), all_vis)) {
- elab_pragmas =tup_with(elab_pragmas, strjoin("su", nam));
- /* subprogram body needed.*/
- }
- else if (tup_memstr(strjoin("su", nam), all_vis)) {
- ; /* already listed.*/
- }
- else {
- warning(strjoin(strjoin(
- "Unknown unit name in ELABORATE pragma ", nam),
- "10.5"), name_node);
- }
- ENDFORTUP(ft1);
- }
-
- void stub_head(int nat, Node id_node) /*;stub_head*/
- {
- /* Find unique name of package or task stub, and verify that it occurs
- * in the proper scope.
- */
-
- char *id;
- Symbol stub_name;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : stub_head");
-
- find_old(id_node);
- id = N_VAL(id_node);
- stub_name = N_UNQ(id_node);
-
- if (SCOPE_OF(stub_name) != scope_name ) {
- #ifdef ERRNUM
- str_errmsgn(15, id, 16, id_node);
- #else
- errmsg_str("specification and stub for % are in different scopes", id,
- "7.1, 9.1", id_node);
- #endif
- }
-
- /* Nature of specification must match that of stub.*/
-
- if ((nat == na_package && (NATURE(stub_name) != na_package_spec
- && NATURE(stub_name) != na_generic_package_spec))
- || (nat == na_task && (NATURE(stub_name) != na_task_type_spec
- && NATURE(stub_name) != na_task_obj_spec)) ) {
- #ifdef ERRNUM
- str_errmsgn(17, id, 16, id_node);
- #else
- errmsg_str("Matching specification not found for stub %", id,
- "7.1, 9.1", id_node);
- #endif
- if (DECLARED(stub_name) == (Declaredmap)0)
- DECLARED(stub_name) = dcl_new(0);
- }
- }
-
- void save_stub(Node node) /*;save_stub*/
- {
- char *kind, *stub_name;
- char *other_unit;
- Symbol name, unit_unam;
- Node spec_node, id_node, stmt_node;
- Tuple env_scope_st, tup;
- Fortup ft1;
- int i, si;
- Stubenv ev;
-
- if (N_KIND(node) == as_subprogram_stub) {
- spec_node = N_AST1(node);
- stmt_node = N_AST3(node);
- id_node = N_AST1(spec_node);
- kind = "su";
- /* Transform the node to as_subprogram_stub_tr nearby dropping off the
- * specification part which contains unnecessary conformance info (in
- * the formal part). Also the node as_procedure (as_function) is
- * unnecessary since this can be determined from the symbol table. Now
- * we move the id_node info (name of the subprogram) to the
- * as_subprogram_stub_tr node directly and move the statments node to
- * the N_AST1 field so that the N_UNQ field (N_AST3) can be used.
- */
- N_KIND(node) = as_subprogram_stub_tr;
- N_AST1(node) = stmt_node;
- N_UNQ(node) = N_UNQ(id_node);
- }
- else { /* package or task stub */
- id_node = node;
- kind = "bo";
- }
-
- /* Save current state of compilation : scope stack and related declared
- * maps, for a subprogram or module stub.
- */
- name = N_UNQ(id_node);
-
- if (cdebug2 > 3) TO_ERRFILE(strjoin("save_stub: ", original_name(name)));
-
- /* In order to uniquely identify the stub, we create for it a name which
- * includes the names of all surrounding scopes, with the exception of
- * the ever-present standard environment and its enclosing scope.
- */
- stub_name = strjoin(kind, original_name(name));
- i = tup_size(open_scopes)-2;
- stub_name = strjoin(stub_name, ".");
- stub_name = strjoin(stub_name, original_name((Symbol) open_scopes[1]));
- if (i != 1) {
- stub_name = strjoin(stub_name, ".");
- stub_name = strjoin(stub_name, original_name((Symbol) open_scopes[i]));
- }
- /* Ada requires that the identifiers of all subunits of a given library
- * unit (as well as the name of the library unit itself) be unique.
- * Check to see of there exists another sub_unit that has the same
- * identifier a different parent but the same eldest ancestor.
- */
- FORTUP(other_unit=(char *), lib_stub, ft1);
- if (streq(unit_name_name(other_unit), unit_name_name(stub_name))
- && streq(stub_ancestor(other_unit), stub_ancestor(stub_name)))
- #ifdef ERRNUM
- errmsgn(18, 19, id_node);
- #else
- errmsg("Subunit identifier not unique", "10.2", id_node);
- #endif
- ENDFORTUP(ft1);
-
- /* Verify that the stub appears immediately within a compilation unit.*/
- if (!streq(original_name(scope_name), unit_name_name(unit_name)))
- #ifdef ERRNUM
- l_errmsgn(20, 21, 19, id_node);
- #else
- errmsg_l("stubs can only appear in the outermost scope of a " ,
- "compilation unit", "10.2", id_node);
- #endif
-
- /* Install the new stub into the library. */
- update_lib_maps(stub_name, 's');
-
- /* Save stub environment.
- * Perhaps some optimization can be done by have a pointer to the symbol
- * table of the parent instead of a complete copy for each stub.
- *
- * open_decls := {};
- * (forall decl = declared(os))
- * open_decls(os) := {[nam, decl(nam), SYMBTABF(decl(nam))] :
- * nam in domain decl};
- * end forall;
- */
-
- /*unit_unam := declared('STANDARD#0')(stub_name(#stub_name)); */
- unit_unam = dcl_get(DECLARED(symbol_standard0), stub_ancestor(stub_name));
-
- env_scope_st = tup_new(0);
- FORTUP(tup=(Tuple), scope_st, ft1);
- env_scope_st = tup_with(env_scope_st, (char *) tup_copy(tup));
- ENDFORTUP(ft1);
- tup = tup_new(4);
- tup[1] = (char *) scope_name;
- tup[2] = (char *) tup_copy(open_scopes);
- tup[3] = (char *) tup_copy(used_mods);
- tup[4] = (char *) tup_copy(vis_mods);
- env_scope_st = tup_with(env_scope_st, (char *) tup);
- /* STUB_ENV(stub_name) :=
- * [ (scope_st + [scope_info]),
- * open_decls,
- * {[vm, visible(vm)] : vm in vis_mods | vm notin ignore},
- * unit_unam,
- * SYMBTABF(unit_unam),
- * CONTEXT
- * ];
- */
- ev = (Stubenv) stubenv_new();
- ev->ev_scope_st = env_scope_st;
- ev->ev_open_decls = unit_symbtab(unit_unam, 's');
- ev->ev_nodes = tup_copy(unit_nodes);
- ev->ev_unit_unam = unit_unam;
- ev->ev_decmap = dcl_copy(DECLARED(unit_unam));
- ev->ev_context = tup_copy(context);
-
- if (NATURE(name) == na_task_obj_spec)
- /* Task object. The stub applies to the task type, not the object. */
- N_UNQ(id_node) = TYPE_OF(name);
-
- N_VAL(node) = stub_name;
- /* Install pointer to saved stub environment */
- si = stub_numbered(stub_name);
- tup = (Tuple) stub_info[si];
- tup[2] = (char *) ev;
- stub_parent_put(stub_name, unit_name);
- stubs_to_write = set_with(stubs_to_write, (char *) si);
-
- /* allocate a fake proper body for the stub. Needed for handling of
- * generic stubs.
- */
- si = unit_number(stub_name);
- pUnits[si]->libInfo.obsolete = string_ds; /*"$D$"*/
- }
-
- static Tuple check_separate(Node unit_node) /*;check_separate*/
- {
- /* This procedure restores the environment saved for a stub,
- * including the original scope stack.
- */
-
- Node a_node, proper_node, spec, name_node;
- char *name, *parent_unit, *outer_most;
- int parent_num;
- Symbol unit_unam;
- Stubenv ev;
-
- a_node = N_AST1(unit_node);
- proper_node = N_AST2(unit_node);
-
- /* Find identifier of subunit. */
- if (N_KIND(proper_node) == as_subprogram) {
- spec = N_AST1(proper_node);
- name_node = N_AST1(spec);
- }
- else /* package body.*/
- name_node = N_AST1(proper_node);
- name = N_VAL(name_node);
-
- if (cdebug2 > 3) TO_ERRFILE(strjoin("checking separate: ", name));
-
- ev = (Stubenv) retrieve_env(a_node, name_node);
- if (ev != (Stubenv)0) {
- scope_st = ev->ev_scope_st;
- unit_unam = ev->ev_unit_unam;
- parent_num = stub_parent_get(unit_name);
- parent_unit = pUnits[parent_num]->name;
- all_vis = tup_with(all_vis, (char *)parent_unit);
- /* put name of outer-most scope in standard*/
- outer_most = stub_ancestor(unit_name);
- dcl_undef(DECLARED(symbol_standard0), outer_most);
- dcl_put(DECLARED(symbol_standard0), outer_most, unit_unam);
-
- /* Reestablish scope of the parent unit, in which compilation of the
- * subunit will take place.
- */
- popscope();
- #ifdef TBSL
- /* Initialize visibility info. */
- (forall vis_vm = vis(vm))
- visible(vm) :
- = vis_vm;
- declared(vm) :
- = vis_vm;
- end forall;
- #endif
- DECLARED(unit_unam) = dcl_copy(ev->ev_decmap);
- symtab_restore(ev->ev_open_decls);
- return ev->ev_context;
- }
- else return (Tuple)0; /* to indicate error */
- }
-
- static Stubenv retrieve_env(Node a_node, Node name_node) /*;retrieve_env*/
- {
- /* Obtain the sequence of parent units of the subunit. It may be an
- * expanded name listing all ancestors.
- */
-
- Node id_node;
- char *name, *expd_name, *stub_nam, *stub_name;
- Fortup ft1;
- Tuple tup;
- int si, stub_err;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : retrieve_env");
-
- name = N_VAL(name_node);
- expd_name = strjoin(name, "");
- if (N_KIND(a_node) != as_simple_name) {
- id_node = N_AST2(a_node);
- expd_name = strjoin(expd_name, ".");
- expd_name = strjoin(expd_name, N_VAL(id_node));
- }
- while (N_KIND(a_node) != as_simple_name) a_node = N_AST1(a_node);
- expd_name = strjoin(expd_name, ".");
- expd_name = strjoin(expd_name, N_VAL(a_node));
- /* retrieve from library the environment in which a stub was
- * first seen.
- */
-
- stub_err = FALSE;
- stub_name = (char *) 0;
- FORTUP(stub_nam=(char *), lib_stub, ft1);
- if (streq(unit_name_names(stub_nam), expd_name)) {
- if (stub_name == (char *)0) stub_name = stub_nam;
- else if (!streq(stub_name, stub_nam)) stub_err = TRUE;
- }
- ENDFORTUP(ft1);
-
- if (stub_name == (char *) 0) stub_err = TRUE;
-
- if (stub_err || !stub_retrieve(stub_name)) {
- #ifdef ERRNUM
- str_errmsgn(22, name, 19, name_node);
- #else
- errmsg_str("cannot find stub for subunit %", name, "10.2" , name_node);
- #endif
- unit_name = strjoin("","");
- return (Stubenv)0;
- }
- remove_obsolete_stubs(expd_name);
- unit_name = strjoin(stub_name, "");
- seq_symbol_n = 0;
- init_compunit();
- si = stub_number(stub_name);
- tup = (Tuple) stub_info[si];
- return (Stubenv) tup[2];
- }
-
- static void remove_obsolete_stubs(char *name) /*;remove_obsolete_stubs*/
- {
- /* If this unit was previously compiled remove possible obsolete stubs
- * of it from library.
- */
-
- char *stub;
- Fortup ft1;
-
- FORTUP(stub=(char *), lib_stub, ft1);
- if (streq(stub_ancestors(stub), name))
- lib_stub_put(stub, (char *)0);
- ENDFORTUP(ft1);
- }
-